package cloud.tianai.ram.policy.client.common.util;

import cloud.tianai.ram.policy.common.util.RamStringUtils;
import cloud.tianai.ram.policy.client.annotation.Action;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Author: 天爱有情
 * @date 2022/3/24 14:08
 * @Description @Acion 注解相关工具包
 */
public class RamAnnotationUtils {

    /**
     * class annotation cache  class -> @Action
     */
    private static final Map<Class, Action> CLASS_CACHE = new ConcurrentHashMap<>(32);
    /**
     * method annotation cache  method -> @Action
     */
    private static final Map<Method, Action> METHOD_CACHE = new ConcurrentHashMap<>(32);
    /**
     * resource dynamic param cache
     */
    private static final Map<String, List<String>> RESOURCE_PARAM_CACHE = new ConcurrentHashMap<>(32);

    /**
     * 从class中提取 @Action
     *
     * @param invocation
     * @return
     */
    public static Action getClassAnnotation(MethodInvocation invocation) {
        return CLASS_CACHE.computeIfAbsent(invocation.getThis().getClass(),
                k -> AnnotationUtils.findAnnotation(invocation.getMethod().getDeclaringClass(), Action.class));
    }

    /**
     * 从method中提取 @Action
     *
     * @param invocation
     * @return
     */
    public static Action getMethodAnnotation(MethodInvocation invocation) {
        return METHOD_CACHE.computeIfAbsent(invocation.getMethod(), k -> AnnotationUtils.findAnnotation(invocation.getMethod(), Action.class));
    }

    public static List<String> getResourceParams(String resourceStr) {
        return RESOURCE_PARAM_CACHE.computeIfAbsent(resourceStr,
                k -> RamStringUtils.extract(k, '{', '}'));
    }

    public static boolean isSkip(Action classAnnotation, Action methodAnnotation) {
        if (methodAnnotation != null) {
            return methodAnnotation.skip();
        } else if (classAnnotation != null) {
            return classAnnotation.skip();
        }
        return false;
    }

    public static boolean getHitThrowError(Action classAnnotation, Action methodAnnotation) {
        if (methodAnnotation != null) {
            return methodAnnotation.hitThrowError();
        } else if (classAnnotation != null) {
            return classAnnotation.hitThrowError();
        }
        return true;
    }

    public static boolean getAutoMatch(Action classAnnotation, Action methodAnnotation) {
        if (methodAnnotation != null) {
            return methodAnnotation.autoMatch();
        } else if (classAnnotation != null) {
            return classAnnotation.autoMatch();
        }
        return true;
    }

    public static String getAction(Action classAnnotation, Action methodAnnotation) {
        if (methodAnnotation != null && StringUtils.hasLength(methodAnnotation.action())) {
            return methodAnnotation.action();
        } else if (classAnnotation != null && StringUtils.hasLength(classAnnotation.action())) {
            return classAnnotation.action();
        }
        return "";
    }


    public static String getResource(Action classAnnotation, Action methodAnnotation) {
        String resourceStr = "";
        if (classAnnotation != null) {
            resourceStr = resourceStr.concat(classAnnotation.resource());
        }
        if (methodAnnotation != null) {
            resourceStr = resourceStr.concat(methodAnnotation.resource());
        }
        return resourceStr;
    }

    public static String getDescription(Action classAnnotation, Action methodAnnotation) {
        String description = "";
        if (classAnnotation != null) {
            description = description.concat(classAnnotation.description());
        }
        if (methodAnnotation != null) {
            description = description.concat(methodAnnotation.description());
        }
        return description;
    }

}
